본문으로 건너뛰기

23.06.20

오늘 한 일

  • 알고리즘 문제 풀이
  • CS 스터디 - 실행컨텍스트

하루 요약

  • 1시 - 5시까지 학교 도서관에서 공부
  • 그 뒤로 UMC 사람들과 술

Excution Context (실행 컨텍스트)

자바스크립트 코드가 실행되고 연산되는 범위를 나타내는 추상적인 개념

즉, 코드들이 실행되기 위한 환경이자 하나의 컨테이너라고 생각하면 된다.

Types of Execution Context

  • Execution Context (EC, 실행 컨텍스트)
    • Global Execution Context (GEC, 전역 실행 컨텍스트)
    • Functional Execution Context (FEC, 함수 실행 컨텍스트)
    • Execution Context inside eval function (Eval 실행 컨텍스트)

Global Execution Context (GEC)

가장 기본적으로 실행되는 컨텍스트

전역 컨텍스트는 자바스크립트 코드가 실행되면 생성된다.

GEC는 단 하나만 존재해야 한다. (JS는 싱글 스레드이기 때문에)

  1. window global object 생성
  2. this에 global object 참조

Functional Execution Context (FEC)

함수가 호출될 때마다 생성

각 함수별로 실행 컨텍스트를 가지고 있지만 실행 컨텍스트는 함수가 호출될 때 만들어진다.

Execution Context Stack (ECS)

실행 컨텍스트가 쌓이는 스택

맨 처음 스택에 쌓이는 컨텍스트는 GEC이다. 코드가 실행되면서 FEC가 생성되면 스택에 쌓이고, 실행이 끝나면 스택에서 제거된다. 모든 js 코드가 실행이 끝나야 GEC가 스택에서 제거된다.

Execution Context 구성

ExecutionContext: {
LexicalEnvironment: {
Environment Records,
Reference to the outer environment,
},
VariableEnvironment: {
Environment Records,
Reference to the outer environment,
}
ThisBinding
}

Lexical Environment & Variable Environment

Variable Environment는 Lexical Environment를 상속하는 관계
Variable Environment과 Lexical Environment 각각 다른 방식으로 선언된 변수들을 관리함

  • Lexical Environment

    • let과 const로 선언된 변수들을 위한 local lexical scope를 단위로 함
    • let, const로 선언된 변수가 메모리에 매핑, 초기값 할당 X
    • 함수선언식으로 선언된 함수가 메모리에 매핑
  • Variable Environment

    • var로 선언된 변수들을 위한 function scope를 단위로 함
    • var로 선언된 변수가 메모리에 매핑, 초기값으로 undefined가 할당

공통된 내부 속성을 알아보자.

Environment Records (환경 레코드)

Environment Record is a specification type used to define the association of Identifiers to specific variables and functions, based upon the lexical nesting structure of ECMAScript code. — ECMAscript

함수와 변수, this, super 등 스코프 내에서 선언된 식별자를 프로퍼티로 저장하는 객체

interface EnvironmentRecord {
DeclarativeEnvironmentRecord: FunctionEnvironmentRecord & ModuleEnvironmentRecord;
ObjectEnvironmentRecord: ObjectEnvironmentRecord;
GlobalEnvironmentRecord: GlobalEnvironmentRecord;
}
  • Declarative Environment Record (선언적 환경 레코드)

    • 스코프 내에서 선언된 식별자를 관리함
    type DeclarativeEnvironmentRecord = {
    HasBinding(N: string): boolean; //Determines if an environment record has a binding for the string N.
    CreateMutableBinding(N: string, D: boolean): void; //Creates a new mutable binding in an environment record.
    CreateImmutableBinding(N: string, S: boolean): void; //Creates a new immutable binding in an environment record.
    InitializeBinding(N: string, V: any): void; //Initializes an immutable binding in an environment record.
    SetMutableBinding(N: string, V: any, S: boolean): void; //Sets the value of an existing mutable binding in an environment record.
    GetBindingValue(N: string, S: boolean): any; //Retrieves the value of an existing binding from an environment record.
    DeleteBinding(N: string): boolean; //Removes a binding from an environment record.
    HasThisBinding(): boolean; //Determines if an environment record establishes a this binding.
    HasSuperBinding(): boolean; //Determines if an environment record establishes a super binding.
    WithBaseObject(): Object; //Returns the binding object for environments that provide ThisBinding.
    };

    type FunctionEnvironmentRecord = {
    [[ThisValue]]: any; //This is the this value used for this invocation of the function.
    [[ThisBindingStatus]]: LexicalEnvironment | initialized | uninitialized; //ThisBindingStatus is either lexicalEnvironment, initialized, or uninitialized.
    [[FunctionObject]]: Function; //The function object whose invocation caused this Environment Record to be created.
    [[NewTarget]]: Object | undefined; //If this Environment Record was created by the [[Construct]] internal method, [[NewTarget]] is the value of the [[Construct]] newTarget parameter. Otherwise, its value is undefined.

    BindThisValue(V: any): void; //Set the [[ThisValue]] and record that it has been initialized.
    GetThisBinding(): any; //Return the value of this Environment Record's this binding. Throws a ReferenceError if the this binding has not been initialized.
    GetSuperBase(): Object | undefined; //Return the object that is the base for super property accesses bound in this Environment Record. The value undefined indicates that such accesses will produce runtime errors.
    };

    type ModuleEnvironmentRecord = {
    CreateImportBinding(N: string, M: Module, N2: string): void; //Create an immutable indirect binding in a Module Environment Record. The String value N is the text of the bound name. M is a Module Record, and N2 is a binding that exists in M's Module Environment Record.
    GetThisBinding(): undefined; //Return the value of this Environment Record's this binding.
    };
  • Object Environment Record (객체 환경 레코드)

    type ObjectEnvironmentRecord = {
    BindingObject: Object; //The binding object of this Environment Record.
    isWithEnvironment: boolean; //Indicates whether this Environment Record is created for a with statement
    };
    • BindingObject(전역 객체)와 연결됨
  • Global Environment Record (전역 환경 레코드)

    • 빌트인 전역 객체, 전역 객체의 프로퍼티 및 스크립트 내의 모든 최상위 선언에 대한 바인딩을 저장함

Reference to the outer environment (외부 환경에 대한 참조)

lexical scope(정적 스코프)를 기준으로 상위 scope의 lexical environment를 참조한다.

각 참조는 단방향 링크드 리스트로 연결되어 있다.

This Binding (this 바인딩)

  • Global Execution Context
    • this는 전역 객체를 참조한다.
  • Functional Execution Context
    • this는 함수를 호출한 객체를 참조한다.
    • arrow function은 함수를 선언할 때 this에 바인딩할 객체가 정적으로 결정된다.(상위 스코프의 this를 참조)

🤔 왜 Lexical Environment와 Variable Environment가 분리되어 있을까?

첫 번째 이유 - 스코프

let, const로 선언한 변수들의 경우 스코프가 block scope이다.

var로 선언한 변수들의 경우 스코프가 function scope이다.

만약, 한 함수 안에 여러

Execution Context Phases

  • Phase
    • Creation Phase
    • Execution Phase

Creation Phase

  1. Lexical Environment 생성
  2. Variable Environment 생성
  3. this 바인딩

⚠️ 값이 변수에 할당되지 않고 메모리에 매핑만 되어있는 상태

  • var로 선언된 변수는 undefined로 초기화
  • letconst로 선언된 변수는 초기화 X

Execution Phase

코드를 실행하면서 실제 값이 할당된다.

예시

var a = 3;
let b = 4;

function func(num) {
var t = 9;
console.log(a + b + num + t);
}

var r = func(4);
creation phaseexecution phase
// GEC's creation phase
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: <uninitialized>,
func: func(){...}
},
outer: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: undefined,
r: undefined
},
outer: null
}
}
// GEC's execution phase
GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: undefined
},
outer 참조: null
}
}
// func's creation phase
FEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
arguments: { num: 4, length: 1 },
},
outer: GECLexicalEnvironment
},
VariableEnvironment: {
EnvironmentRecord: {
t: undefined
},
outer: GECLexicalEnvironment
}
}
// func's execution phase
FEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
arguments: { num: 4, length: 1 },
},
outer: GECLexicalEnvironment
},
VariableEnvironment: {
EnvironmentRecord: {
t: 9
},
outer: GECLexicalEnvironment
}
}

FEC가 스택에서 제거되고 GEC의 r이 20으로 초기화된다.

GEC {
ThisBinding: window,
LexicalEnvironment: {
EnvironmentRecord: {
b: 4,
func: func(){...}
},
outer 참조: null
},
VariableEnvironment: {
EnvironmentRecord: {
a: 3,
r: 20
},
outer 참조: null
}
}


내일 할 일

  • 알고리즘 문제 풀이
  • CS 스터디 - 실행컨텍스트 ECMAScript 다시 읽고 정리, 브라우저 동작 원리 공부
  • 함수형 프로그래밍 스터디 공부 및 참가
  • 오후 10시 테오 스프린트 1일차